package cn.yunyichina.provider.register.service.impl;

import cn.yunyichina.provider.framework.common.PKGenerator;
import cn.yunyichina.provider.framework.data.SpringContextHandler;
import cn.yunyichina.provider.framework.dubbo.service.*;
import cn.yunyichina.provider.iface.entity.base.OrderExtVo;
import cn.yunyichina.provider.iface.entity.common.ResCommon;
import cn.yunyichina.provider.iface.entity.common.Response;
import cn.yunyichina.provider.iface.entity.hisiface.register.CancelRegisterVo;
import cn.yunyichina.provider.iface.entity.hisiface.register.RefundRegisterVo;
import cn.yunyichina.provider.register.utils.RegUtil;
import cn.yunyichina.utils.commons.DateUtils;
import cn.yunyichina.utils.convert.JsonUtils;
import cn.yunyichina.utils.log.Log;
import cn.yunyichina.utils.log.constant.LogParamType;
import cn.yunyichina.utils.log.constant.LogScene;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.collections.map.HashedMap;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 挂号退费
 * Created by Administrator on 2017/6/22.
 */
@Service
public class RefundServiceImpl {

    private Logger logger = LoggerFactory.getLogger(RefundServiceImpl.class);

    @Autowired
    private RegRecordServiceImpl regRecordService;

    @Resource
    private Properties yaml;


    /** 挂号取消 退费
     * yyt.register.reg.info.cancel --> yyt.register.refund.reg.record.ack
     * @param data
     * @param sessionId
     * @return
     * @throws Exception
     */
    public Response ackRefundRegRecord(String data, String sessionId) throws Exception {
        Response response = new Response();
//        logger.info("取消挂号--->method:cancelRegInfo,data:" + data + "！");
        Map<String,Object> requestVo = JsonUtils.parseObject(data, Map.class);
        String orderNo = (String) requestVo.get("order_no");
        Log.i(LogScene.REGISTER_REFUND,"yyt.register.refund.reg.record.ack", LogParamType.REQUEST,orderNo,
                "request data=" +JsonUtils.toJsonString(data));
        if(StringUtils.isBlank(orderNo)){
            response.setResultCodeAndMessage("-1","订单号不能为空");
        }


        Map<String, Object> dataMap = new HashMap<String, Object>();
        dataMap.put("order_no", orderNo);
        dataMap.put("order_type", OrderExtVo.ORDER_TYPE_REGISTER);
//        logger.info("cancelRegInfo, yyt.base.order.by.orderno.get request=" + JSON.toJSONString(dataMap));
        Response ordResponse = BaseService.callUnderlineFromInternal(sessionId, "yyt.base.order.by.orderno.get",
                JsonUtils.toJsonString(dataMap));
        logger.info("cancelRegInfo, yyt.base.order.by.orderno.get ordResponse=" + JSON.toJSONString(ordResponse));
        if (!"0".equals(ordResponse.getResultCode())) {
            response.setResultCodeAndMessage(ordResponse.getResultCode(), ordResponse.getResultMessage());
            return response;
        }
        OrderExtVo order = JsonUtils.parseObject(ordResponse.getResult(), OrderExtVo.class);

        if(order == null){
            response.setResultCodeAndMessage("3002", "订单不存在。");
            return response;
        }
        if(OrderExtVo.ORDER_STATUS_SUCCESS != order.getOrderStatus() && OrderExtVo.ORDER_STATUS_REVISION != order.getOrderStatus()
                &&  OrderExtVo.ORDER_STATUS_REPLACE != order.getOrderStatus()){
            response.setResultCodeAndMessage("3002", "订单不是成功状态，不能取消");
            return response;
        }
        if(OrderExtVo.ORDER_STATUS_SUCCESS != order.getOrderStatus() &&  OrderExtVo.ORDER_STATUS_REVISION != order.getOrderStatus()
                &&  OrderExtVo.ORDER_STATUS_REPLACE != order.getOrderStatus() &&
                ( order.getPayAmount() != 0 && OrderExtVo.ORDER_PAY_STATUS_PAYED != order.getPayStatus() )){
            response.setResultCodeAndMessage("3002", "订单状态不是已支付状态,不允许取消");
            return response;
        }

        String regType ;//= RegUtil.getRegType(vo.getScheduleTime());
        //判断是预约，还是当天的
        int days = DateUtils.daysBetween(DateUtils.StringToDateYMD(order.getCreatedTime()), DateUtils.StringToDateYMD(order.getScheduleTime()));
        if (days == 0) {
            regType = RegUtil.REG_TYPE_DUTY;
        } else if (days > 0) {
            regType = RegUtil.REG_TYPE_APPOINTMENT;
        } else {
            response.setResultCodeAndMessage("3002", "未知的挂号类别regType");
            return response;
        }


        /*** 是否符合取消挂号规则/条件限制 *******/
        Map<String, Object> checkCancleMap = checkCanCancelReg(order,regType);
        boolean canCancle = (boolean) checkCancleMap.get("canCancle");
        if(canCancle) {
            Map<String, Object> extraParams = JsonUtils.parseObject(order.getExtraParams(), Map.class);
            if (order.getPayAmount() == 0 || order.getPayStatus() < OrderExtVo.ORDER_PAY_STATUS_PAYED){
                //支付金额为0或者不用支付的订单的调用解锁接口
                CancelRegisterVo cancelRegisterVo = new CancelRegisterVo();
                cancelRegisterVo.setHospitalCode(order.getOrgCode());
                cancelRegisterVo.setBranchCode(order.getBranchCode());
                cancelRegisterVo.setHisOrdNum(order.getHisOrderNo());
                cancelRegisterVo.setCancelTime(DateUtils.dateToString(new Date()));
                cancelRegisterVo.setYytOrdNum(order.getOrderNo());
                cancelRegisterVo.setRegType(regType);
                ResCommon resCommon = HisifaceService.getHisifaceClient().cancelRegister(cancelRegisterVo);
//                logger.info("不用支付，取消挂号调his解锁接口，request={}, response={}" ,JSON.toJSONString(cancelRegisterVo), JSON.toJSONString(resCommon));
                Log.i(LogScene.REGISTER_REFUND,"yyt.register.refund.reg.record.ack", LogParamType.REQUEST,orderNo,
                        "不用支付，取消挂号调his解锁接口cancelRegister，request=" +JsonUtils.toJsonString(cancelRegisterVo));
                Log.i(LogScene.REGISTER_REFUND,"yyt.register.refund.reg.record.ack", LogParamType.RESPONSE,orderNo,
                        "不用支付，取消挂号调his解锁接口cancelRegister，response=" +JsonUtils.toJsonString(resCommon));

                if (!"0".equals(resCommon.getResultCode())) {
                    response.setResultCodeAndMessage(resCommon.getResultCode(), resCommon.getResultMessage()==null?"调用医院接口退费失败":resCommon.getResultMessage());
                    return response;
                }
                order.setOrderStatusCancel();//解锁后状态改成7 取消
                order.setUpdateTime(DateUtils.getDatetime());
            }else {
                //挂号退费确认接口暂时不调用，直接调退费接口
                RefundRegisterVo refundRegisterVo = new RefundRegisterVo();
                if (1 == order.getIsInsurance()) {
                    //医保退款
                    refundRegisterVo.setRefundAmount(String.valueOf(order.getTotalAmount()));
                    Map<String, String> ybMap = new HashedMap();
                    ybMap.put("cancel_serial_no", (String) extraParams.get("cancel_serial_no"));
                    ybMap.put("cancel_bill_no", (String) extraParams.get("cancel_bill_no"));
                    refundRegisterVo.setExtendParams(JSONObject.toJSONString(ybMap));
                } else {
                    refundRegisterVo.setRefundAmount(String.valueOf(order.getPayAmount()));
                    refundRegisterVo.setHisOrdNum(order.getHisOrderNo());
                }

                refundRegisterVo.setHospitalCode(order.getOrgCode());
                refundRegisterVo.setBranchCode(order.getBranchCode());
                refundRegisterVo.setYytOrdNum(order.getOrderNo());
                refundRegisterVo.setYytRefOrdNum(order.getOrderNo());
                refundRegisterVo.setRefundMode(String.valueOf(order.getPayMode()));

                refundRegisterVo.setRefundTime(DateUtils.dateToString(new Date()));
                refundRegisterVo.setRefundReason((String) requestVo.get("refund_reason"));
                refundRegisterVo.setRegType(regType);

                //港大退费增加pat_card_no
                Map<String,String> extMap = new HashedMap();
                extMap.put("pat_card_type",String.valueOf(order.getMedicalCardType()));
                extMap.put("pat_card_no",order.getMedicalCardNo());
                if(extraParams.get("adm_no") != null) {
                    //福田中医院需求，写单返回出参的adm_no
                    extMap.put("adm_no", (String) extraParams.get("adm_no"));
                }
                refundRegisterVo.setExtendParams(JsonUtils.toJsonString(extMap));


                ResCommon resCommon = HisifaceService.getHisifaceClient().refundRegister(refundRegisterVo);
//                logger.info("ackRefundRegRecord, his refundRegister:request={},response={}", JSON.toJSONString(refundRegisterVo), JSON.toJSONString(resCommon));
                Log.i(LogScene.REGISTER_REFUND,"yyt.register.refund.reg.record.ack", LogParamType.REQUEST,orderNo,
                        "call his refundRegister，request=" +JsonUtils.toJsonString(refundRegisterVo));
                Log.i(LogScene.REGISTER_REFUND,"yyt.register.refund.reg.record.ack", LogParamType.RESPONSE,orderNo,
                        "call his refundRegister，response=" +JsonUtils.toJsonString(resCommon));
                if (!"0".equals(resCommon.getResultCode())) {
                    response.setResultCodeAndMessage("6101", StringUtils.isBlank(resCommon.getResultMessage())?"调用医院接口退费失败":resCommon.getResultMessage());
                    return response;
                }

                order.setOrderStatusCancel();//his退费成功，订单状态改成取消

                //第三方原渠道退费
                Map<String, Object> jsonMap = new HashMap<String, Object>();
                jsonMap.put("hospital_code", order.getOrgCode());
                jsonMap.put("order_no", order.getOrderNo());
                if (1 == order.getIsInsurance()) {
                    jsonMap.put("his_order_no", extraParams.get("cancel_bill_no"));
                    jsonMap.put("his_serial_no", extraParams.get("cancel_serial_no"));
                    jsonMap.put("refund_amount", order.getTotalAmount());
                } else {
                    jsonMap.put("his_order_no", order.getHisOrderNo());
                    jsonMap.put("refund_amount", order.getPayAmount());
                }

                jsonMap.put("refund_time", DateUtils.dateToString(new Date()));
                jsonMap.put("refund_reason", "挂号取消");
                jsonMap.put("refund_flag", 1);
                jsonMap.put("push_type", 0);
                Response refundResponse = PayService.callUnderlineFromInternal("", "yyt.pay.refund.channel.origin", JsonUtils.toJsonString(jsonMap));
//                logger.info("ackRefundRegRecord：退费返回" + JsonUtils.toJsonString(refundResponse));
                Log.i(LogScene.REGISTER_REFUND,"yyt.register.refund.reg.record.ack", LogParamType.RESPONSE,orderNo,
                        "yyt.pay.refund.channel.origin，退费返回=" +JsonUtils.toJsonString(refundResponse));
                if ("0".equals(refundResponse.getResultCode())) {
                    order.setPayStatusRefunded();
                    response.setResultCodeAndMessage("0", "取消挂号成功");
                } else {
                    order.setPayStatusWaitRefund();//第三方退费失败，状态改成待退费
                    response.setResultCodeAndMessage(refundResponse.getResultCode(), refundResponse.getResultMessage());
                }
            }

            //更新订单状态
            logger.info("ackRefundRegRecord, 退费成功，更改订单状态 updateOrder =" + JSONObject.toJSONString(order));
            BaseService.callUnderlineFromInternal("",
                    "yyt.base.order.update", JsonUtils.toJsonString(order));
            // 消息推送
            try {
                String method = "yyt.message.msg.template.send";
                String url="";

                String scheduleTime = order.getScheduleTime();
                if (scheduleTime != null && scheduleTime.length() > 10) {
                    scheduleTime = scheduleTime.substring(0, 10);
                    if(extraParams.get("begin_time") != null && extraParams.get("begin_time").equals(extraParams.get("end_time"))){
                        scheduleTime += " " + extraParams.get("begin_time");
                    }else{
                        scheduleTime += " " + extraParams.get("begin_time") + "-" + extraParams.get("end_time");
                    }
                }
                String platformType = "2";
                if (order.getPayMode() !=null && String.valueOf(order.getPayMode()).startsWith("1")) {
                    platformType = "1";
                } else  if (order.getPayMode() !=null && String.valueOf(order.getPayMode()).startsWith("2")) {
                    platformType = "2";
                }

                Map<String, Object> msgMap = new HashedMap();
                msgMap.put("user_type", "2");
                msgMap.put("to_user", order.getOpenId());
                msgMap.put("order_no", order.getOrderNo());
                msgMap.put("platform_type", platformType);

                msgMap.put("org_app_code", order.getPlatformOrgAppCode());
                msgMap.put("org_code", order.getOrgCode());
                msgMap.put("template_code", "21003");
                Map<String, Object> msgContent = new HashedMap();
                msgContent.put("first", "您好，您的挂号已取消成功。");
                if("stszxyy".equals(order.getOrgCode())){
                    if("1".equals(msgMap.get("platform_type"))) {
                        msgContent.put("keyword1", order.getUserName());
                        msgContent.put("keyword2", scheduleTime);
                        msgContent.put("keyword3", order.getDeptName());
                        msgContent.put("keyword4", order.getDoctorName());
                        String remark = "感谢您的使用。";
                        msgContent.put("remark", remark);
                    }else if("2".equals(msgMap.get("platform_type"))) {
                        msgContent.put("keyword1", order.getUserName());
                        msgContent.put("keyword2", scheduleTime);
                        msgContent.put("keyword3", order.getDoctorName());
                        msgContent.put("keyword4", order.getDeptName());
                        String remark = "感谢您的使用。";
                        msgContent.put("remark", remark);
                    }
                }else {
                    msgContent.put("keyword1", order.getUserName());
                    msgContent.put("keyword2", scheduleTime);
                    msgContent.put("keyword3", order.getDeptName());
                    msgContent.put("keyword4", order.getDoctorName());
                    String remark = "感谢您的使用。";
                    msgContent.put("remark", remark);
                }

                msgMap.put("msg_content", JSON.toJSONString(msgContent));
                url = yaml.getProperty("order.reg.url") + "order_no=" + order.getOrderNo() + "&app_code=" + order.getPlatformOrgAppCode() + "&open_id=" + order.getOpenId() + "&app_id=" + order.getPayAppId();
                msgMap.put("url", url);
                Response messageResponse = MessageService.callHumpFromInternal(method, JsonUtils.toJsonString(msgMap));
//                logger.info("ackRefundRegRecord挂号取消, 调用message模块,request={}，response={}="
//                        ,JsonUtils.toJsonString(msgMap),JsonUtils.toJsonString(messageResponse));
                Log.i(LogScene.REGISTER_REFUND,"yyt.register.refund.reg.record.ack", LogParamType.REQUEST,orderNo,
                        "ackRefundRegRecord挂号取消, 调用message模块,request=" +JsonUtils.toJsonString(msgMap));
                Log.i(LogScene.REGISTER_REFUND,"yyt.register.refund.reg.record.ack", LogParamType.RESPONSE,orderNo,
                        "ackRefundRegRecord挂号取消, 调用message模块,response=" +JsonUtils.toJsonString(messageResponse));

                if("yytc06514ff54dbe32d".equals(order.getPlatformOrgAppCode())){
                    //云医通插入消息记录
                    Map<String,Object> yytMap = new HashedMap();
                    yytMap.put("id", PKGenerator.generateId());
                    yytMap.put("org_id", order.getOrgId());
                    yytMap.put("org_name",order.getOrgName());
                    yytMap.put("org_code",order.getOrgCode());
                    yytMap.put("user_id",order.getUserId());
                    yytMap.put("user_name",order.getUserName());
//            yytMap.put("library_template_code",msgCenter.getTemplateId());
                    yytMap.put("msg_title","挂号取消通知");
                    yytMap.put("is_read",1);

                    Map<String,Object> contentMap = new HashedMap();
                    List<Map<String,String>> msgTemplateContents = new ArrayList<>();
                    Map<String,String> firstMap = new HashedMap();
                    firstMap.put("keyword","first");
                    firstMap.put("note","");
                    firstMap.put("value","您好，您的挂号已取消成功。");
                    msgTemplateContents.add(firstMap);

                    Map<String,String> k1Map = new HashedMap();
                    k1Map.put("keyword","姓名");
                    k1Map.put("note","");
                    k1Map.put("value",order.getUserName());
                    msgTemplateContents.add(k1Map);

                    Map<String,String> k2Map = new HashedMap();
                    k2Map.put("keyword","就诊时间");
                    k2Map.put("note","");
                    k2Map.put("value",scheduleTime);
                    msgTemplateContents.add(k2Map);

                    Map<String,String> k3Map = new HashedMap();
                    k3Map.put("keyword","科室");
                    k3Map.put("note","");
                    k3Map.put("value",order.getDeptName());
                    msgTemplateContents.add(k3Map);

                    Map<String,String> k4Map = new HashedMap();
                    k4Map.put("keyword","医生");
                    k4Map.put("note","");
                    k4Map.put("value",order.getDoctorName());
                    msgTemplateContents.add(k4Map);

                    contentMap.put("msgTemplateContents", msgTemplateContents);

                    List<Map<String,String>> msgTemplateFunctions = new ArrayList<>();
                    Map<String,String> funcMap = new HashedMap();
                    funcMap.put("functionCode","location='" +url + "'" );
                    funcMap.put("functionName","点击查看挂号详情");
                    msgTemplateFunctions.add(funcMap);

                    contentMap.put("msgTemplateFunctions",msgTemplateFunctions);
                    yytMap.put("msg_content",JsonUtils.toJsonString(contentMap));
                    yytMap.put("created_time",DateUtils.dateToString(new Date()));

                    messageResponse = MessageService.callHumpFromInternal("yyt.message.messagehistory.add",JsonUtils.toJsonString(yytMap));
                    logger.info("订单号" + order.getOrderNo() + ", 调用message模块,yyt.message.messagehistory.add request={}，response={}",
                            JsonUtils.toJsonString(yytMap),JsonUtils.toJsonString(messageResponse));

                }
            } catch (Exception e) {
                logger.error("挂号支付写单外部接口, 挂号支付成功后消息推送失败:", e);
            }

        }else{
            //不符合取消挂号规则
            response.setResultCodeAndMessage("-1", (String) checkCancleMap.get("tip"));
        }

        return response;

    }

    /**
     *  是否符合取消挂号规则/条件限制 *******
     *
     */
    private Map<String, Object> checkCanCancelReg(OrderExtVo vo,String regType) {
        Map<String, Object> map = new HashMap<>();
        try {
            int closeType = 0;//取消截止时间点类型
            Long overTime = null;
            int cancelEndTime = 0;
            if (RegUtil.REG_TYPE_DUTY.equals(regType)) {
                if (!"1".equals(RegUtil.getRule(vo.getOrgCode(), RegUtil.IS_SUPPORT_REFUND_ON_DUTY,"2"))) {
                    map.put("canCancle", false);
                    map.put("tip", RegUtil.NOT_SUPPORT_REFUND_ON_DUTY_MSG);
                    return map;
                }
                String[] cancelOnDutyEndTimes = RegUtil.getRule(vo.getOrgCode(), RegUtil.CANCEL_ON_DUTY_END_TIME,"1").split(",");
                closeType = Integer.parseInt(cancelOnDutyEndTimes[0]);
                if (closeType > 1 && cancelOnDutyEndTimes.length > 1) {
                    cancelEndTime = Integer.parseInt(cancelOnDutyEndTimes[1]);
                }

            } else {
                //预约挂号
                if (!"1".equals(RegUtil.getRule(vo.getOrgCode(), RegUtil.IS_SUPPORT_REFUND_APPOINTMENT,"1"))) {
                    map.put("canCancle", false);
                    map.put("tip", RegUtil.NOT_SUPPORT_REFUND_APPOINTMENT_MSG);
                    return map;
                }
                String[] cancelOnDutyEndTimes = RegUtil.getRule(vo.getOrgCode(), RegUtil.CANCEL_APPOINTMENT_END_TIME,"1").split(",");
                closeType = Integer.parseInt(cancelOnDutyEndTimes[0]);
                if (closeType > 1 && cancelOnDutyEndTimes.length > 1) {
                    cancelEndTime = Integer.parseInt(cancelOnDutyEndTimes[1]);
                }
            }
            //就诊时间
            Date scheduleDate = DateUtils.StringToDateYMD(vo.getScheduleTime());
            Map<String, Object> extraParams = JsonUtils.parseObject(vo.getExtraParams(), Map.class);
            String beginTime = "00:00", endTime = "23:59";
            if (extraParams != null) {
                beginTime = (String) extraParams.get("begin_time");
                endTime = (String) extraParams.get("end_time");
            }

            //就诊开始时间
            Date scheduleStartTime = DateUtils.StringToDate(DateUtils.getDateStr(scheduleDate) + " " + beginTime + ":00");
            Date scheduleEndTime = DateUtils.StringToDate(DateUtils.getDateStr(scheduleDate) + " " + endTime + ":00");

            GregorianCalendar scheduleCalendar = new GregorianCalendar();
            Long nowTime = new Date().getTime();
            /**
             *  取消挂号截止时间点
             *  1、不限制 就诊当天几点
             *  2、就诊当天几点
             *  3、就诊时间段开始前多少分钟
             *  4、就诊时间段结束前多少分钟
             */
            switch (closeType) {
                case 1:
                    //不限制情况  当前时间+1 始终使overTime > nowTime
                    overTime = nowTime + 1;
                    break;
                case 2:
                    //2、就诊当天几点
                    scheduleCalendar.setTime(scheduleDate);
                    scheduleCalendar.set(Calendar.HOUR_OF_DAY, cancelEndTime);
                    overTime = scheduleCalendar.getTimeInMillis();
                    break;
                case 3:
                    //3、就诊时间段开始前多少分钟
                    scheduleCalendar.setTime(scheduleStartTime);
                    overTime = scheduleCalendar.getTimeInMillis() - cancelEndTime * 60 * 1000;
                    break;
                case 4:
                    //就诊时间段结束前多少分钟
                    scheduleCalendar.setTime(scheduleEndTime);
                    overTime = scheduleCalendar.getTimeInMillis() - cancelEndTime * 60 * 1000;
                    break;
            }

            if (nowTime >= overTime) {
                map.put("canCancle", false);
                map.put("tip", RegUtil.OVER_REFUND_ENDTIME_MSG);

            } else {
                map.put("canCancle", true);
            }

            if("stszxyy".equals(vo.getOrgCode()) &&  DateUtils.daysBetween(DateUtils.today(),DateUtils.getDateStr(scheduleDate)) == 0){
                //汕头取消挂号特殊规则判断
                String now = new SimpleDateFormat("HH:mm").format(new Date());
                String middleTime = "12:00";
                if(middleTime.compareTo(beginTime) > 0 && now.compareTo("08:00") > 0){
                    map.put("canCancle", false);
                    map.put("tip","上午8点后不能取消当天上午的号源");
                }
                if( now.compareTo("14:00") > 0){
                    map.put("canCancle", false);
                    map.put("tip","下午14点后不能取消当天下午的号源");
                }
            }
        }catch (Exception e){
            e.printStackTrace();
            map.put("canCancle", false);
            map.put("tip", "解析挂号规则出现异常：" + e.getMessage());
        }
        return map ;
    }
}
